package daily.year2023.m1;

public class M1D2 {
    //              消除游戏
    //列表 arr 由在范围 [1, n] 中的所有整数组成，并按严格递增排序。请你对 arr 应用下述算法：
    //    从左到右，删除第一个数字，然后每隔一个数字删除一个，直到到达列表末尾。
    //    重复上面的步骤，但这次是从右到左。也就是，删除最右侧的数字，然后剩下的数字每隔一个删除一个。
    //    不断重复这两步，从左到右和从右到左交替进行，直到只剩下一个数字。
    //给你整数 n ，返回 arr 最后剩下的数字。

    //--------------------------------------------------------------------------
    //              自己写的，击败百分之59
    // 思路：类似于双指针，设置首尾指针，然后寻找规律，缩减范围，最终两指针相同时就是所要的结果
    /*public int lastRemaining(int n) {
        if (n == 1) {
            return 1;
        }
        //flag用于判断当前是从头开始还是从尾开始，1是从头开始，-1是从尾开始
        int flag = -1,front = 2,rear,span = 4;

        rear = (n & 1) == 1 ? n-1 : n;

        while (rear > front) {
            if (front % span == rear % span) {
                front += span / 2;
                rear -= span / 2;
            }else{
                if (flag == -1) {
                    rear -= span / 2;
                }else{
                    front += span / 2;
                }
            }

            flag *= -1;
            span *= 2;
        }
        return front;
    }*/
    //--------------------------------------------------------------------------

    //--------------------------------------------------------------------------
    //                  官方题解：等差数列模拟
    //思路：每次删除完之后的数列都是等差数列，可以利用这个性质来做此题
    //  等差数列的规律：有公差，首项确定，数列的数目确定就可以确定这个数列
    //解题：使用k来记录删除的次数，初始值为0；a记录的是首项；length记录数列的项数；span记录公差；
    //  1、若k是偶数，则从首项开始删除：
    //        (1)当前数列的项数为奇数，首尾都要删除，所以更新首项：a = a + span;
    //        (2)当前数列的项数为偶数，只删除首项，更新首项：a = a + span;
    //  2、若k是奇数，则从尾项开始删除：
    //        (1)当前数列的项数为奇数，首尾都要删除，所以更新首项：a = a + span;
    //        (2)当前数列的项数为偶数，只删除尾项，但是尾项可以使用首项和项数来确定，所以，不需要删除尾项，首项不变即可
    //每次删除完毕，更新项数：length = length / 2;
    //           还要更新公差：span = span * 2;

    public int lastRemaining(int n){
        int k = 0,a = 1,length = n,span = 1;

        while (length > 1) {

            if ((k & 1) == 0) {
                a += span;
            }else{
                a = (length & 1) == 1 ? a + span : a ;
            }

            k++;
            span *= 2;
            length /= 2;
        }

        return a;
    }
}
